/*
 * ringbufref.hpp
 *
 *  Created on: 2017年2月3日
 *      Author: work
 */

#ifndef INCLUDE_DM_RINGBUFREF_HPP_
#define INCLUDE_DM_RINGBUFREF_HPP_

#include <dm/ringpos_c.hpp>

namespace dm{

template<typename Tv,typename Ts,typename Tc>
class CRingBufRef{
	CRingBufRef( const CRingBufRef& );
	CRingBufRef& operator=( const CRingBufRef& );

public:
	typedef CRingPosC<Ts,Tc> pos_t;

	CRingBufRef( Tv* buf,Ts size ):m_d(buf),m_p(size){}

	inline const Ts& getSize()const{
		return m_p.getSize();
	}

	inline const pos_t& getPos()const{
		return m_p;
	}

	inline Ts getDataLen( const pos_t& p )const{
		return m_p - p;
	}

	inline bool isDataOverFlow( const pos_t& p )const{
		return m_p.isNoLessThanACycle(p);
	}

	inline void push( const Tv& v ){
		m_d[m_p.getPos()] = v;
		++m_p;
	}

	void push( const Tv* buf,Ts size );

	inline const Tv& at( const pos_t& p )const{
		return at(p.getPos());
	}

	inline Ts getData( Tv* buf,const Ts& size,pos_t p )const{
		return getDataAndMove(buf,size,p);
	}

	Ts getDataAndMove( Tv* buf,const Ts& size,pos_t& p )const;

private:
	Tv* m_d;
	pos_t m_p;
};

template<typename Tv,typename Ts,typename Tc>
void CRingBufRef<Tv,Ts,Tc>::push( const Tv* buf,Ts size ){
	while( size>0 ){
		push(*buf);
		++buf;
		--size;
	}
}

template<typename Tv,typename Ts,typename Tc>
Ts CRingBufRef<Tv,Ts,Tc>::getDataAndMove( Tv* buf,const Ts& size,pos_t& p )const{
	Ts i = 0;
	for( ;i<size && p!=m_p;++i,++p )
		buf[i] = at(p);
	return i;
}

}

#endif /* INCLUDE_DM_RINGBUFREF_HPP_ */
